package nio.netty.service;

import com.alibaba.fastjson.JSONObject;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import nio.netty.pojo.Json;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MainService{
    //处理消息的内部类
    class ClientMessageHandler extends SimpleChannelInboundHandler<String> {

        /**
         * description:  这是读取信息函数，服务器的消息将由它接收
         * version: 1.0 <br>
         * date: 2021/4/7 13:36 <br>
         * author: 温家清
         *
         * @param ctx 这是上下文
         * @param msg 这是从客户端发来的消息
         * @return void
         */
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, String msg) {
            putString(msg);
        }
        /**
         * description: 这是处理channel异常的函数
         * version: 1.0 <br>
         * date: 2021/4/7 13:38 <br>
         * author: 温家清
         *
         * @param ctx 这是上下文
         * @param cause 这是在捕获在pipeline发生的异常
         * @return void
         */
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            ctx.close();

        }
    }
    /**
     * description: 这个类是用来处理聊天室的消息
     * version: 1.0 <br>
     * date: 2021/4/7 13:45 <br>
     * author: 温家清
     */
    class Receiver implements Runnable{
        public void run(){
            String str;
            try{
                while(flag){
                    if((str=getString())!=null){
                        System.out.println(str);
                    }
                    Thread.sleep(1000);

                }
            } catch(Exception e){
                e.printStackTrace();
            }
        }
    }
    private String id;
    private volatile boolean flag=true;
    private ChannelFuture future;
    private Channel channel;
    private final Scanner scanner;
    private final List<String> list = Collections.synchronizedList(new ArrayList<>());
    private final Lock lock = new ReentrantLock();
    /**
     * description: 构造函数：初始化客户端
     * version: 1.0 <br>
     * date: 2021/4/7 13:48 <br>
     * author: 温家清
     *
     * @param future 这是用来回调的，可发送消息
     * @return void
     */
    public MainService(ChannelFuture future){
        this.future = future;
        this.channel = future.channel();
        this.scanner = new Scanner(System.in);
        addHandle();

    }
    /**
     * description: 客户端设有一个Collections.synchronizedList线程安全的list,用来存储从服务端发来的消息，这是从list获取消息
     * version: 1.0 <br>
     * date: 2021/4/7 13:49 <br>
     * author: 温家清
     *
     * @param
     * @return java.lang.String
     */
    public String getString(){
        String str = null;
        lock.lock();
        try {
            if(!list.isEmpty())
                str = list.remove(0);
        }catch (Exception e){
            e.printStackTrace();
        }
        finally {
            lock.unlock();
        }
        return str;
    }
    /**
     * description: 客户端设有一个Collections.synchronizedList线程安全的list,用来存储从服务端发来的消息，这是往list放置消息
     * version: 1.0 <br>
     * date: 2021/4/7 13:50 <br>
     * author: 温家清
     *
     * @param msg 消息
     * @return void
     */
    public void putString(String msg){
        list.add(msg);
    }
    /**
     * description: 这是验证用户的账号密码是否非法，这里不进行验证
     * version: 1.0 <br>
     * date: 2021/4/7 13:52 <br>
     * author: 温家清
     *
     * @param id 账号
     * @param pwd 密码
     * @return boolean
     */
    public boolean confirm(String id,String pwd){
        return true;
    }
    /**
     * description: 这是注册模块
     * version: 1.0 <br>
     * date: 2021/4/7 13:52 <br>
     * author: 温家清
     *
     * @param
     * @return void
     */
    public void register() throws InterruptedException {

        System.out.println("请输入账号：");
        String id = scanner.nextLine();
        System.out.println("请输入密码");
        String pwd = scanner.nextLine();

        String str;
        if(confirm(id,pwd)){
            channel.writeAndFlush(string2Json("register",id,"",pwd));
            for(int i=0;i<10;i++){

                if((str = getString()) !=null){
                    if(str.equals("register:success") ){
                        System.out.println("注册成功");
                        return;
                    }
                    else if(str.equals("register:fail")){
                        System.out.println("注册失败：用户已存在");
                        return;
                    }
                }
                Thread.sleep(2000);
            }
            System.out.println("注册失败：服务器无响应");
        }else{
            System.out.println("用户密码不符合规定");
        }

    }
    /**
     * description: 这是登录模块 <br>
     * version: 1.0 <br>
     * date: 2021/4/7 13:54 <br>
     * author: 温家清
     *
     * @param
     * @return void
     */
    public void login() throws Exception{

        System.out.println("请输入账户：");
        String id = scanner.nextLine();
        System.out.println("请输入密码");
        String pwd = scanner.nextLine();
        String str;
        if(confirm(id,pwd)){
            channel.writeAndFlush(string2Json("login",id,"",pwd));
            for(int i=0;i<20;i++){

                if((str = getString())!=null){
                    if(str.equals("login:success") ){
                        System.out.println("登录成功");
                        this.id = id;
                        enterChat();
                        return;
                    }
                    else if( str.equals("login:fail")){
                        System.out.println("登录失败，账号密码错误");
                        return;
                    }
                    else if(str.equals("login:repeat")){
                        System.out.println("该用户已登录");
                        return;
                    }
                }


                Thread.sleep(1000);
            }
            System.out.println("登录失败：服务器无响应");

        }
    }
    /**
     * description: 这是消息转换函数，用户输入的消息需要转换为json字符串，实体类型为pojo文件夹下的Json <br>
     * version: 1.0 <br>
     * date: 2021/4/7 13:56 <br>
     * author: 温家清
     *
     * @param message 需要格式化的消息
     * @return java.lang.String
     */
    public String string2Json(String message) {
        Json json;
        if(message.startsWith("#")){
            String to_id = message.split("#",3)[1];
            String body = message.split("#",3)[2];
            json = new Json("message",id,to_id,body);


        }else{
            json = new Json("message",id,"",message);
        }
        return JSONObject.toJSONString(json);
    }
    /**
     * description: 消息转换函数重载 <br>
     * version: 1.0 <br>
     * date: 2021/4/7 13:57 <br>
     * author: 温家清
     * 
     * @param type 消息类型
     * @param id 用户自己id
     * @param to_id 目的地id
     * @param message 消息内容
     * @return java.lang.String
     */ 
    public String string2Json(String type,String id,String to_id,String message){
        return JSONObject.toJSONString(new Json(type,id,to_id,message));
    }
    public void enterChat() throws Exception {
        channel.writeAndFlush(string2Json("chat",id,"","enter:chat01"));
        String str = "";
        System.out.println("正在进入聊天室");
        String flag2;
        for(int i =0 ;i<20;i++){
            if((flag2 = getString())!=null){
                if(flag2.equals("enter:chat01")){
                    System.out.println("已在聊天室");
                    Receiver receiver = new Receiver();
                    Thread thread = new Thread(receiver);
                    thread.start();
                    System.out.println("可以聊天了");
                    while(scanner.hasNextLine()){
                        str = scanner.nextLine();
                        if(str.startsWith("#退出")){

                            break;
                        }
                        channel.writeAndFlush(string2Json(str));
                    }
                    //杀死线程；
                    flag = false;
                    if(str.startsWith("#退出")){
                        break;
                    }

                }else{
                    System.out.println("聊天室异常");
                }
            }
            Thread.sleep(1000);
        }


    }
    /**
     * description: 这是为pipeline添加处理器 <br>
     * version: 1.0 <br>
     * date: 2021/4/7 13:59 <br>
     * author: 温家清
     * 
     * @param
     * @return void
     */ 
    public void addHandle(){
        future.channel().pipeline().addLast(new ClientMessageHandler());
    }
    /**
     * description: 这是登录界面逻辑处理 <br>
     * version: 1.0 <br>
     * date: 2021/4/7 14:00 <br>
     * author: 温家清
     * 
     * @param
     * @return void
     */ 
    public void start(){

        System.out.println("1:登录");
        System.out.println("2:注册");
        System.out.println("3:退出");
        label:
        while(scanner.hasNextLine()){

            String str = scanner.nextLine();
            switch (str) {
                case "1":
                    try {

                        login();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    break;
                case "2":
                    try {

                        register();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                case "3":

                    break label;
                default:
                    System.out.println("输入错误,请重新输入");
                    break;
            }
            System.out.println("1:登录");
            System.out.println("2:注册");
            System.out.println("3:退出");
        }
        scanner.close();
        System.exit(0);
    }
}

